/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package meteocal.gui;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import meteocal.business.boundary.EventDeleteFacade;
import meteocal.business.boundary.EventFacade;
import meteocal.business.boundary.NotificationFacade;
import meteocal.business.boundary.UserFacade;
import meteocal.business.control.DateUtils;
import meteocal.business.entity.Event;
import meteocal.business.entity.EventDeleted;
import meteocal.business.entity.Notification;
import meteocal.business.security.boundary.UserManager;
import meteocal.business.security.entity.User;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.DefaultScheduleModel;
import org.primefaces.model.ScheduleEvent;
import org.primefaces.model.ScheduleModel;

/**
 *
 * @author Francesca
 */

@Named(value = "showCalendarBean")
@SessionScoped
public class ShowCalendarBean implements Serializable {

    private List<Event> eventInCalendar;
    private List<Notification> invitationNotification;
    private List<Notification> cancellationNotification;
    private List<Notification> modificationNotification;
    private List<EventDeleted> eventCancellationList;
    private List<Event> eventModificationList;
    private String owner;
    private Event oneEvent;
    private long st_date;
    private long en_date;
    private Notification in;
    private Event eventInvitation;
    private EventDeleted eventCancellation;
    private Event eventModification;
    private ArrayList<Event> eventInvitationList;
    private Event eventSelected;
    private EventDeleted eventSelectedDeleted;
    private Event eventSelectedModified;
    private Event eventSelectedBadWeather;
  
    private ScheduleModel eventModel;
    private ScheduleEvent event = new DefaultScheduleEvent();
    
    private User user;
    private Event eventoSelezionato; 
    private EventDeleted eventoSelezionatoEliminato;
    private Event eventoSelezionatoModificato;
    private List<Notification> invitationList;
    private Integer idNotification;
    private String idPending;
    private Integer idEventSelected;
    private Notification notification;
    private Event eventToUpdate;
    private ArrayList<Event> badWeatherEvents ;
    private Collection<Event> eventOfUser;
    private List<Notification> badNotificationList;
    private Event badWeatherEvent;
    private List<Notification> reschedulingList; 
    private ArrayList<Event> reschedulingEvents;
    private Event reschedulingEvent;
    private Event selectedReschedulingEvent;
    private Notification reSuggestion;
    private GregorianCalendar suggestedDate;
    
            
    private String addingUser; 
    private String removingUser; 
    
    @EJB
    EventFacade ef;
    
    @EJB
    NotificationFacade nf;

    @EJB
    UserFacade uf;
    
    @EJB
    UserManager um;
    
    @EJB
    EventDeleteFacade edf;
   
  
    
   
   
    @PostConstruct
    public void init(){
       eventModel = new DefaultScheduleModel();
       List<Event> listaEventi = ef.searchEventOfUser(ef.getUser());
       List<Event> listaEventiPartecipazioni = ef.searchInParticipants(ef.getUser());
       listaEventi.addAll(listaEventiPartecipazioni);
       for(Event e: listaEventi){
           oneEvent = e;
           st_date = oneEvent.getStarting_date().getTime()+oneEvent.getStartingTime().getTime();
           en_date = oneEvent.getEnding_date().getTime()+oneEvent.getEndingTime().getTime();
           eventModel.addEvent(new DefaultScheduleEvent(oneEvent.getName(),new Date(st_date), new Date(en_date)));
           
       }
       showCancellation();
       showModification();
       showInvitation();
       showBadWeather();
       showRescheduling();
    }

    //inserire i dati dell'evento
    public void showInvitation(){
        eventInvitationList = new ArrayList<Event>();
        invitationNotification = nf.checkInvitation(um.getLoggedUser().getUsername());
        if(invitationNotification != null && !invitationNotification.isEmpty()){
            for (Notification in: invitationNotification){
                
               eventInvitation = in.getIdEvent();
               eventInvitationList.add(eventInvitation);
            }
        }
    }

    /**
     * This method show the cancellation of an event
     */
    public void showCancellation(){
        eventCancellationList = new ArrayList<EventDeleted>();
        cancellationNotification = nf.checkCancellation(um.getLoggedUser().getUsername());
        if(cancellationNotification != null && !cancellationNotification.isEmpty()){
            for (Notification in: cancellationNotification){
                Integer idEvent = in.getIdEvent().getIdEvent();
                eventCancellation = edf.eventDetails(idEvent);
                eventCancellationList.add(eventCancellation);
            }
        }
    }
    
        
    /**
     * This method shows the modification of an event
     */
    public void showModification(){
        eventModificationList = new ArrayList<Event>();
        modificationNotification = nf.checkModification(um.getLoggedUser().getUsername());
        if(modificationNotification != null && !modificationNotification.isEmpty()){
            for (Notification in: modificationNotification){
                eventModification = in.getIdEvent();
                eventModificationList.add(eventModification);
            }
        
    }
    }
    
    /**
     * This method shows all the notification of bad weather for events the user is involved
     * @return 
     */
     public void showBadWeather() {
        Integer idEvent;
        badWeatherEvents = new ArrayList<Event>();
        badNotificationList = nf.checkBadWeather(um.getLoggedUser().getUsername());
        if (badNotificationList != null && !badNotificationList.isEmpty()) {
            for (Notification in : badNotificationList) {
                badWeatherEvent = in.getIdEvent();
                badWeatherEvents.add(badWeatherEvent);
            }
        }
    }
     
     /**
     * This method shows all the proposition of rescheduling for the events the user created
     * @return 
     */
     public void showRescheduling() {
        Integer idEvent;
        reschedulingEvents = new ArrayList<Event>();
        reschedulingList = nf.checkRescheduling(um.getLoggedUser().getUsername());
        if (reschedulingList != null && !reschedulingList.isEmpty()) {
            for (Notification in : reschedulingList) {
                reSuggestion = in;
                reschedulingEvent = in.getIdEvent();
                reschedulingEvents.add(reschedulingEvent);
            }
        }
    }
        
    /**
     * If the user accepts a rescheduling suggestion, the system moves the event.
     */ 
    public String acceptRescheduling(){
        
        Event event = reSuggestion.getIdEvent();
        event.setStarting_date(reSuggestion.getReschedulingDate());
        DateUtils du = new DateUtils();
        long diff = du.getDateDiff(event.getStarting_date(), event.getEnding_date(), TimeUnit.DAYS);
        event.setEnding_date(new Date(event.getStarting_date().getTime()+diff));
        
        Collection<User> participants = event.getParticipants();
        for(User u: participants){
            nf.create(event, u.getUsername(), 3);
        }
        
        ef.updateEvent(event);
        return "main-page?faces-redirect=true";
    }
    
    public String refuseRescheduling(){
        nf.remove(reSuggestion);
        
        return "main-page?faces-redirect=true";
    }
        
    

    public String deleteCancellation(){
        Integer type = 2;
        Notification notification;
        user = um.getLoggedUser();
        notification = nf.checkIdNotification(ef.find(eventoSelezionatoEliminato.getIdEvent()),user.getUsername(),type);
        nf.removeNotification(notification.getIdNotification());
        init();
        return "main-page?faces-redirect=true";
    }
    
        public String deleteModification(){
        Integer type = 3;
        Notification notification;
        user = um.getLoggedUser();
        System.out.println(user.getUsername());
        System.out.println(eventoSelezionatoModificato.getIdEvent());
        notification = nf.checkIdNotification(eventoSelezionatoModificato,user.getUsername(),type);
        System.out.println(notification.getIdNotification());
        nf.removeNotification(notification.getIdNotification());
        init();
        return "main-page?faces-redirect=true";
    }
    
    public String deleteInvitedUser(){
        Integer type = 1;
        Notification notification;
        Collection<User> pendingUser;
        user = um.getLoggedUser();
        System.out.println(user);
        System.out.println(eventoSelezionato.getIdEvent());
        notification = nf.checkIdNotification(eventoSelezionato,user.getUsername(),type); 
        nf.removeNotification(notification.getIdNotification());
        pendingUser = eventoSelezionato.getPendingUsers();
        ef.merge(eventoSelezionato);
        ef.flush();
        init();
        return "main-page?faces-redirect=true";
    }
    
     /*
     * When a user accept the invitation the notification is deleted 
     * and the user is inserted into invited users
     */
    public String insertInvitedUser(){ 
        Integer type = 1;
        Notification notification;
        Collection<User> partecipatingUsers;
        user = um.getLoggedUser();
        notification = nf.checkIdNotification(eventoSelezionato,user.getUsername(),type);
        nf.removeNotification(notification.getIdNotification());
        eventoSelezionato.getPendingUsers().remove(user);
        partecipatingUsers = eventoSelezionato.getParticipants();
        partecipatingUsers.add(user);
        eventoSelezionato.setParticipants(partecipatingUsers);
        ef.merge(eventoSelezionato);
        ef.flush();
        init();
        return "main-page?faces-redirect=true";
    }
    
    public Integer InvitationIdFromEvent(){
        for(Notification in: invitationNotification){
            if(in.getIdEvent() == eventToUpdate){
                return invitationNotification.indexOf(eventToUpdate);
            }
        }
        return null;
    }
    
    public Event getEventInvitation() {
        return eventInvitation;
    }

    public void setEventInvitation(Event eventInvitation) {
        this.eventInvitation = eventInvitation;
    }
    
    public List<Event> getEventInCalendar() {
        return eventInCalendar;
    }

    public void setEventInCalendar(List<Event> eventInCalendar) {
        this.eventInCalendar = eventInCalendar;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    public Event getOneEvent() {
        return oneEvent;
    }

    public void setOneEvent(Event oneEvent) {
        this.oneEvent = oneEvent;
    }

    public ScheduleModel getEventModel() {
        return eventModel;
    }

    public void setEventModel(ScheduleModel eventModel) {
        this.eventModel = eventModel;
    }

    public ScheduleEvent getEvent() {
        return event;
    }

    public void setEvent(ScheduleEvent event) {
        this.event = event;
    }
    
    public void onEventSelect(SelectEvent selectEvent){
       event = (ScheduleEvent) selectEvent.getObject();
       
    }
    
    public void onDateSelect(SelectEvent selectEvent){
      event = new DefaultScheduleEvent("",(Date) selectEvent.getObject() ,(Date) selectEvent.getObject());
    }
    
    public ShowCalendarBean() {
    }

    public Collection<Event> getEventOfUser() {
        return eventOfUser;
    }

    public void setEventOfUser(Collection<Event> eventOfUser) {
        this.eventOfUser = eventOfUser;
    }

    public List<Notification> getInvitationNotification() {
        return invitationNotification;
    }

    public void setInvitationNotification(List<Notification> invitationNotification) {
        this.invitationNotification = invitationNotification;
    }

    public Notification getIn() {
        return in;
    }

    public void setIn(Notification in) {
        this.in = in;
    }

    public Event getEventSelected() {
        return eventSelected;
    }

    public void setEventSelected(Event eventSelected) {
        this.eventSelected = eventSelected;
    }

    public ArrayList<Event> getEventInvitationList() {
        return eventInvitationList;
    }

    public void setEventInvitationList(ArrayList<Event> eventInvitationList) {
        this.eventInvitationList = eventInvitationList;
    }

    

    public Event getEventSelectedBadWeather() {
        return eventSelectedBadWeather;
    }

    public void setEventSelectedBadWeather(Event eventSelectedBadWeather) {
        this.eventSelectedBadWeather = eventSelectedBadWeather;
    }

    public Notification getReSuggestion() {
        return reSuggestion;
    }

    public void setReSuggestion(Notification reSuggestion) {
        this.reSuggestion = reSuggestion;
    }
   
    public Event getEventoSelezionato() {
        return eventoSelezionato;
    }

    public void setEventoSelezionato(Event eventoSelezionato) {
        this.eventoSelezionato = eventoSelezionato;
    }

    public String getAddingUser() {
        return addingUser;
    }

    public void setAddingUser(String addingUser) {
        this.addingUser = addingUser;
    }

    public String getRemovingUser() {
        return removingUser;
    }

    public void setRemovingUser(String removingUser) {
        this.removingUser = removingUser;
    }

    public List<Notification> getReschedulingList() {
        return reschedulingList;
    }

    public void setReschedulingList(List<Notification> reschedulingList) {
        this.reschedulingList = reschedulingList;
    }

    public ArrayList<Event> getReschedulingEvents() {
        return reschedulingEvents;
    }

    public void setReschedulingEvents(ArrayList<Event> reschedulingEvents) {
        this.reschedulingEvents = reschedulingEvents;
    }

    public Event getReschedulingEvent() {
        return reschedulingEvent;
    }

    public void setReschedulingEvent(Event reschedulingEvent) {
        this.reschedulingEvent = reschedulingEvent;
    }

    
     
    /**
     * Add to the events in the calendar the event of a given user with a public calendar. 
     * @return 
     */
    public String addUserCalendar(){
        
        List<Event> listaEventi = ef.searchEventOfUser(addingUser);
        List<Event> listaEventiPartecipazioni = ef.searchInParticipants(addingUser);
        listaEventi.addAll(listaEventiPartecipazioni);
        for (Event e : listaEventi) {
            oneEvent = e;
            st_date = oneEvent.getStarting_date().getTime() + oneEvent.getStartingTime().getTime();
            en_date = oneEvent.getEnding_date().getTime() + oneEvent.getEndingTime().getTime();
            
            if(oneEvent.getPrivacyLevel()){
              eventModel.addEvent(new DefaultScheduleEvent(oneEvent.getName(), new Date(st_date), new Date(en_date)));  
            } else {
              String hiddenEvent = oneEvent.getCreator().getUsername()+" made this private";
              eventModel.addEvent(new DefaultScheduleEvent(hiddenEvent, new Date(st_date), new Date(en_date)));
            }    

       }
        
        return "main-page?faces-redirect=true"; 
    }

    public List<EventDeleted> getEventCancellationList() {
        return eventCancellationList;
    }

    public void setEventCancellationList(List<EventDeleted> eventCancellationList) {
        this.eventCancellationList = eventCancellationList;
    }

    public EventDeleted getEventSelectedDeleted() {
        return eventSelectedDeleted;
    }

    public void setEventSelectedDeleted(EventDeleted eventSelectedDeleted) {
        this.eventSelectedDeleted = eventSelectedDeleted;
    }

    public EventDeleted getEventoSelezionatoEliminato() {
        return eventoSelezionatoEliminato;
    }

    public void setEventoSelezionatoEliminato(EventDeleted eventoSelezionatoEliminato) {
        this.eventoSelezionatoEliminato = eventoSelezionatoEliminato;
    }

    public List<Event> getEventModificationList() {
        return eventModificationList;
    }

    public void setEventModificationList(List<Event> eventModificationList) {
        this.eventModificationList = eventModificationList;
    }

    public Event getEventSelectedModified() {
        return eventSelectedModified;
    }

    public void setEventSelectedModified(Event eventSelectedModified) {
        this.eventSelectedModified = eventSelectedModified;
    }

    public Event getEventoSelezionatoModificato() {
        return eventoSelezionatoModificato;
    }

    public void setEventoSelezionatoModificato(Event eventoSelezionatoModificato) {
        this.eventoSelezionatoModificato = eventoSelezionatoModificato;
    }

    public ArrayList<Event> getBadWeatherEvents() {
        return badWeatherEvents;
    }

    public void setBadWeatherEvents(ArrayList<Event> badWeatherEvents) {
        this.badWeatherEvents = badWeatherEvents;
    }

    public List<Notification> getBadNotificationList() {
        return badNotificationList;
    }

    public void setBadNotificationList(List<Notification> badNotificationList) {
        this.badNotificationList = badNotificationList;
    }

    public Event getBadWeatherEvent() {
        return badWeatherEvent;
    }

    public void setBadWeatherEvent(Event badWeatherEvent) {
        this.badWeatherEvent = badWeatherEvent;
    }

    public Event getSelectedReschedulingEvent() {
        return selectedReschedulingEvent;
    }

    public void setSelectedReschedulingEvent(Event selectedReschedulingEvent) {
        this.selectedReschedulingEvent = selectedReschedulingEvent;
    }

    public GregorianCalendar getSuggestedDate() {
        return suggestedDate;
    }

    public void setSuggestedDate(GregorianCalendar suggestedDate) {
        this.suggestedDate = suggestedDate;
    }
    
    
   
    /**
     * Remove from the events in the calendar the events of a given user previously added
     * @return 
     */
    public String removeUserCalendar(){
        
        List<Event> listaEventi = ef.searchEventOfUser(removingUser);
        List<Event> listaEventiPartecipazioni = ef.searchInParticipants(removingUser);
        listaEventi.addAll(listaEventiPartecipazioni);
        
        List<ScheduleEvent> temp = eventModel.getEvents();
        
        for(int i=0; i<listaEventi.size(); i++){
            Event toRemove = listaEventi.get(i);
            st_date = toRemove.getStarting_date().getTime() + toRemove.getStartingTime().getTime();
            en_date = toRemove.getEnding_date().getTime() + toRemove.getEndingTime().getTime();
            
            ScheduleEvent tempE;
            
            if(toRemove.getPrivacyLevel()){
              tempE = new DefaultScheduleEvent(toRemove.getName(), new Date(st_date), new Date(en_date)); 
            } else {
              String hiddenEvent = toRemove.getCreator().getUsername()+" made this private";
              tempE = new DefaultScheduleEvent(hiddenEvent, new Date(st_date), new Date(en_date));
            }
            
           
           
            temp.remove(tempE);
        }
        
        eventModel.clear();
        eventModel = new DefaultScheduleModel(temp);
        
        
        return "main-page?faces-redirect=true";
        
        
        
    }
    
    public String deleteEvent(Event event){
        
            List<ScheduleEvent> temp = eventModel.getEvents();
            Event toRemove = event;
            st_date = toRemove.getStarting_date().getTime() + toRemove.getStartingTime().getTime();
            en_date = toRemove.getEnding_date().getTime() + toRemove.getEndingTime().getTime();
            ScheduleEvent tempE;
            tempE = new DefaultScheduleEvent(toRemove.getName(), new Date(st_date), new Date(en_date)); 
            temp.remove(tempE);
            eventModel.clear();
            eventModel = new DefaultScheduleModel(temp);
            return "main-page?faces-redirect=true";
    }
    
    public String createEvent(Event event){
        
            List<ScheduleEvent> temp = eventModel.getEvents();
            Event toAdd = event;
            st_date = toAdd.getStarting_date().getTime() + toAdd.getStartingTime().getTime();
            en_date = toAdd.getEnding_date().getTime() + toAdd.getEndingTime().getTime();
            ScheduleEvent tempE;
            tempE = new DefaultScheduleEvent(toAdd.getName(), new Date(st_date), new Date(en_date)); 
            temp.add(tempE);
            eventModel.clear();
            eventModel = new DefaultScheduleModel(temp);
            return "main-page?faces-redirect=true";
    }
    
}
